package presentation.control;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JTable;

import presentation.data.DataUtil;
import presentation.data.ManageProductsData;
import presentation.data.MessagesUtil;
import presentation.gui.AddEditCatalog;
import presentation.gui.AddEditProduct;
import presentation.gui.EbazaarMainFrame;
import presentation.gui.MaintainCatalogTypes;
import presentation.gui.MaintainProductCatalog;
import usecasecontrol.ComboObserver;
import usecasecontrol.GuiUtil;
import business.exceptions.BackendException;
import business.exceptions.UIException;
import business.exceptions.UnauthorizedException;
import business.externalinterfaces.ProductSubsystem;
import business.productsubsystem.ProductSubsystemFacade;

public class ManageProductsUIControl {
	private static final Logger LOG = 
    	Logger.getLogger(ManageProductsUIControl.class.getName());
    
    //// control MaintainCatalogTYpes
	class AddCatalogListener implements ActionListener {

        public void actionPerformed(ActionEvent evt) {    	
        	addEditCatalog  = new AddEditCatalog(GuiUtil.ADD_NEW, null);
        	maintainCatalogTypes.setVisible(false);    
        	mainFrame.getDesktop().add(addEditCatalog);
        	addEditCatalog.setVisible(true);        	
        }        	
	}
	
	class EditCatalogListener implements ActionListener {	
		final String ERROR = "Error";	    
        public void actionPerformed(ActionEvent evt) {
        	JTable table = maintainCatalogTypes.getTable();
        	try {
        		String selectedCatalog = DataUtil.getSelectedValueFromTable(table);
        		maintainCatalogTypes.setVisible(false);						       														
        		AddEditCatalog editWindow = new AddEditCatalog(GuiUtil.EDIT, selectedCatalog);
        		mainFrame.getDesktop().add(editWindow);
        		editWindow.setVisible(true);
        		
        	} catch(UIException e) {
        		MessagesUtil.displayErrorMsg(maintainCatalogTypes, e.getMessage());
        		
        	}
        }
	}
	
	class DeleteCatalogListener implements ActionListener {
		final String ERROR_MESSAGE = "Please select a row.";
		final String ERROR = "Error";	    
        public void actionPerformed(ActionEvent evt) {
        	
            JTable table = maintainCatalogTypes.getTable();
            
        	int selectedRow = table.getSelectedRow();
        	if(selectedRow >= 0) {
				// Students: code goes here.
        		MessagesUtil.displayInfoMsg(maintainCatalogTypes, "Need to write code for this!" );	
        		
        	}
        	else {
        		MessagesUtil.displayErrorMsg(maintainCatalogTypes, ERROR_MESSAGE);
        	}        	
        }
	}	
    class MaintainProductActionListener implements ActionListener, Callback {
    	ManageProductsData data = null;
        /* this method is called when LoginControl needs this class to load products 
         */
        public void doUpdate() {
        	try {
        		Authorization.checkAuthorization(maintainProductCatalog, DataUtil.custIsAdmin());
        	} catch(UnauthorizedException e) {   
            	MessagesUtil.displayErrorMsg(maintainProductCatalog, 
            			e.getMessage());
            	return;
            }
        	
            if (maintainProductCatalog != null){
            	String catalog = maintainProductCatalog.getCatalogGroup();
            	try {
            		List<String[]> associatedProducts = data.getProductsRelatedToCatalog(catalog);           		
            		maintainProductCatalog.setCatalogGroup(catalog);
            		maintainProductCatalog.refreshData(associatedProducts);
            		mainFrame.getDesktop().add(maintainProductCatalog);
            		maintainProductCatalog.setVisible(true);
            	}
            	catch(BackendException e) {
            		MessagesUtil.displayErrorMsg(maintainProductCatalog, 
							  MessagesUtil.DATABASE_ERROR); 
            	}
            }
        }   
         public void actionPerformed(ActionEvent e) {
        	 data = ManageProductsData.getInstance();
             if(maintainProductCatalog==null) {
            	 maintainProductCatalog = new MaintainProductCatalog();
             }            
             if(!DataUtil.isLoggedIn()) {                
                 LoginUIControl loginControl = 
                     new LoginUIControl(maintainProductCatalog,
                                      mainFrame, this);
                 loginControl.startLogin();
             }   
             else {
                 doUpdate();
             }
        }
    }

   
    class MaintainCatalogTypesActionListener implements ActionListener, Callback {
    	ManageProductsData data = null;
        /* this method is called when LoginControl needs this class to load catalogs 
         */
        public void doUpdate() {
        	try {
        		Authorization.checkAuthorization(maintainCatalogTypes, DataUtil.custIsAdmin());
        	} catch(UnauthorizedException e) {   
            	MessagesUtil.displayErrorMsg(maintainCatalogTypes, 
            			e.getMessage());
            	return;
            }
            //implement by requesting catalog list from Product Subsystem
        	try{
        		List<String[]> catalogs = data.getCatalogs();        		
        		maintainCatalogTypes.updateModel(catalogs);
        		mainFrame.getDesktop().add(maintainCatalogTypes);
        		maintainCatalogTypes.setVisible(true);
        	}
        	catch(BackendException e){
        		MessagesUtil.displayErrorMsg(maintainCatalogTypes, MessagesUtil.DATABASE_ERROR); 
        		
        	}             
            
        }   
         public void actionPerformed(ActionEvent e) {
        	 data = ManageProductsData.getInstance();
        	 maintainCatalogTypes  = new  MaintainCatalogTypes();
             if(!DataUtil.isLoggedIn()) {           
                 LoginUIControl loginControl = 
                     new LoginUIControl(maintainCatalogTypes,
                                      mainFrame, this);
                 loginControl.startLogin();
             } 
             else {
                 doUpdate();                 
             }
        }
    }	
	
	class BackToMainListener implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
			BrowseSelectUIControl.getInstance().makeMainFrameVisible();
		    maintainCatalogTypes.dispose();		
		}
	}	
   
    
	//// control MaintainProductCatalog
	class AddProductListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
        	
       		//no field values need to be passed into AddEditProduct when adding a new product
       		//so we create an empty Properties instance
        	Properties emptyProductInfo = new Properties();
        	
        	String catalogType = maintainProductCatalog.getCatalogGroup();
        	addEditProduct = new AddEditProduct(GuiUtil.ADD_NEW, catalogType, emptyProductInfo);
        	//maintainProductCatalog.setVisible(false);
        	mainFrame.getDesktop().add(addEditProduct);
        	addEditProduct.setVisible(true);
        	
        }        	
 
	}
	
	
	class EditProductListener implements ActionListener {
		ManageProductsData data;    
        public void actionPerformed(ActionEvent evt) {
        	data = ManageProductsData.getInstance();
        	JTable table = maintainProductCatalog.getTable();
        	//CustomTableModel model = maintainProductCatalog.getModel();
        	String catalogType = maintainProductCatalog.getCatalogGroup();
        	Properties productInfo = null;
        	try {
        		productInfo = data.getProductFieldValues(table);
        		AddEditProduct editProd = new AddEditProduct(GuiUtil.EDIT,catalogType, productInfo);
        		mainFrame.getDesktop().add(editProd);
        		editProd.setVisible(true);
        	} catch(UIException e) {
        		MessagesUtil.displayErrorMsg(maintainProductCatalog, e.getMessage());
        	}
        	
        }
	}
	class DeleteProductListener implements ActionListener {
		final String ERROR_MESSAGE = "Please select a row.";
		final String ERROR = "Error";		    
        public void actionPerformed(ActionEvent evt) {
            JTable table = maintainProductCatalog.getTable();
        	int selectedRow = table.getSelectedRow();
        	if(selectedRow >= 0) {
 				// Students: code goes here.
        		
				JOptionPane.showMessageDialog(maintainProductCatalog, 
										  "Need to write code for this!", 
										  "Information", 
										  JOptionPane.INFORMATION_MESSAGE);        		
        		
        	}
        	else {
        		MessagesUtil.displayErrorMsg(maintainProductCatalog, MessagesUtil.SELECT_ROW_MSG);
        	}        
        }
	}	
	
	class SearchProductListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
        	//Students: code goes here
        	

        }
	}
	class BackToMainFromProdsListener implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
				BrowseSelectUIControl.getInstance().makeMainFrameVisible();
			    maintainProductCatalog.dispose();		
		}
	}	
	
	// control AddEditCatalog
	class SaveAddEditCatListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
				JOptionPane.showMessageDialog(addEditCatalog, 
										  "Need to write code for this!", 
										  "Information", 
										  JOptionPane.INFORMATION_MESSAGE); 
 
        }
	}
	/**
	 * Returns the user to the previous screen
	 */
	class BackFromAddEditCatListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
        	
        	maintainCatalogTypes.setVisible(true);
        	addEditCatalog.dispose();

        }
	}	
  
	////  control AddEditProduct
	
	class SaveAddEditProductListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
				JOptionPane.showMessageDialog(addEditProduct, 
										  "Need to write code for this!", 
										  "Information", 
										  JOptionPane.INFORMATION_MESSAGE); 
 
        }
	}
	class BackFromAddEditProductListener implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
        	
           	maintainProductCatalog.setVisible(true);
        	addEditProduct.dispose();


        }
	}
	
	static class ComboAction extends AbstractAction {
		private static final long serialVersionUID = -6362862518012806665L;
		private static final ComboAction INSTANCE = new ComboAction();
		ComboObserver[] observers = null;
		
		/* 
		 * The values of the observers array change from null to non-null as
		 * application proceeds.
		 */
		private void updateObservers() {
			observers = new ComboObserver[]{maintainProductCatalog, addEditProduct};
		}
		public void actionPerformed(ActionEvent evt) {
			updateObservers();
			@SuppressWarnings("rawtypes")
			String selectedValue = (String)((JComboBox)evt.getSource()).getSelectedItem();
			ProductSubsystem prodSS = new ProductSubsystemFacade();
			try {
				List<String[]> associatedProducts =
					business.util.ProductUtil.extractProductInfoForManager(
						prodSS.getProductList(selectedValue));
				for(ComboObserver o: observers) {
					if(o != null) {
						o.setCatalogGroup(selectedValue);
						o.refreshData(associatedProducts);					
					} else {
						LOG.warning("an observer was null");
					}
				}
			}
			catch(BackendException e) {
				e.printStackTrace();
			}
		}		
	}
	
    
    
    ///////// PUBLIC INTERFACE -- for getting instances of listeners ///
	//mainFrame
    public ActionListener getMaintainProductActionListener(EbazaarMainFrame w){
            return (new MaintainProductActionListener());
    }     
        
    public ActionListener getMaintainCatalogTypesActionListener(EbazaarMainFrame w){
            return (new MaintainCatalogTypesActionListener());
    }     
	// MaintainCatalogTypes
    public ActionListener getAddCatalogListener(MaintainCatalogTypes w){
        return (new AddCatalogListener());
    }     
    
    public ActionListener getEditCatalogListener(MaintainCatalogTypes w){
        return (new EditCatalogListener());
    } 
    
    public ActionListener getDeleteCatalogListener(MaintainCatalogTypes w){
        return (new DeleteCatalogListener());
    } 
    
    public ActionListener getBackToMainListener(MaintainCatalogTypes w){
        return (new BackToMainListener());
    } 
    
    // MaintainProductCatalog
    public ActionListener getAddProductListener(MaintainProductCatalog w){
        return (new AddProductListener());
    } 
    public ActionListener getEditProductListener(MaintainProductCatalog w){
        return (new EditProductListener());
    } 
    public ActionListener getDeleteProductListener(MaintainProductCatalog w){
        return (new DeleteProductListener());
    } 
    public ActionListener getSearchProductListener(MaintainProductCatalog w){
        return (new SearchProductListener());
    } 
    public ActionListener getBackToMainFromProdsListener(MaintainProductCatalog w){
        return (new BackToMainFromProdsListener());
    }  
    public Action getComboAction(Component c){
        return c == null ? null : ComboAction.INSTANCE;
    }
    
    // AddEditCatalog
    public ActionListener getSaveAddEditCatListener(AddEditCatalog w){
        return (new SaveAddEditCatListener());
    } 
    public ActionListener getBackFromAddEditCatListener(AddEditCatalog w){
        return (new BackFromAddEditCatListener());
    }  
    
    // AddEditProduct
    public ActionListener getSaveAddEditProductListener(AddEditProduct w){
        return (new SaveAddEditProductListener());
    } 
    public ActionListener getBackFromAddEditProductListener(AddEditProduct w){
        return (new BackFromAddEditProductListener());
    }          
    
    ////////  PUBLIC ACCESSORS to register screens controlled by this class////    
    public void setMaintainCatalogTypes(MaintainCatalogTypes w){
        maintainCatalogTypes = w;
    }     
    public void setMaintainProductCatalog(MaintainProductCatalog w){
        maintainProductCatalog = w;
    }  
    public void setAddEditCatalog(AddEditCatalog w){
        addEditCatalog = w;
    }  
    public void setAddEditProduct(AddEditProduct w){
        addEditProduct = w;
    } 
    public void setMainFrame(EbazaarMainFrame f){
        mainFrame = f;
    }    
    
    /////// screens -- private references
    private static MaintainCatalogTypes maintainCatalogTypes;
    private static MaintainProductCatalog maintainProductCatalog;
    private static AddEditCatalog addEditCatalog;
    private static AddEditProduct addEditProduct;
    private static EbazaarMainFrame mainFrame;
	
    /////// make this class a singleton
    private static ManageProductsUIControl instance = new ManageProductsUIControl();
    public static ManageProductsUIControl getInstance(){
        return instance;
    }
    private ManageProductsUIControl(){}
    
   
}
